﻿#include "EdgeExtract.h"

namespace EdgeExtract {
static cv::Mat sobel[8] = {(cv::Mat_<float>(3, 3) << -1,  0,  1,
                                                     -2,  0,  2,
                                                     -1,  0,  1),  // 0°
                           (cv::Mat_<float>(3, 3) << -2, -1,  0,
                                                     -1,  0,  1,
                                                      0,  1,  2),  // 45°
                           (cv::Mat_<float>(3, 3) << -1, -2, -1,
                                                      0,  0,  0,
                                                      1,  2,  1),  // 90°
                           (cv::Mat_<float>(3, 3) <<  0, -1, -2,
                                                      1,  0, -1,
                                                      2,  1,  0),  // 135°
                           (cv::Mat_<float>(3, 3) <<  1,  0, -1,
                                                      2,  0, -2,
                                                      1,  0, -1),  // 180°
                           (cv::Mat_<float>(3, 3) <<  2,  1,  0,
                                                      1,  0, -1,
                                                      0, -1, -2),  // 225°
                           (cv::Mat_<float>(3, 3) <<  1,  2,  1,
                                                      0,  0,  0,
                                                     -1, -2, -1),  // 270°
                           (cv::Mat_<float>(3, 3) <<  0,  1,  2,
                                                     -1,  0,  1,
                                                     -2, -1,  0)}; // 315°

static double xTable[8] = {cos(  0.0 * CV_PI / 180.0) * 0.5,
                    cos( 45.0 * CV_PI / 180.0) * sqrt(2.0) * 0.5,
                    cos( 90.0 * CV_PI / 180.0) * 0.5,
                    cos(135.0 * CV_PI / 180.0) * sqrt(2.0) * 0.5,
                    cos(180.0 * CV_PI / 180.0) * 0.5,
                    cos(225.0 * CV_PI / 180.0) * sqrt(2.0) * 0.5,
                    cos(270.0 * CV_PI / 180.0) * 0.5,
                    cos(315.0 * CV_PI / 180.0) * sqrt(2.0) * 0.5};

static double yTable[8] = {sin(  0.0 * CV_PI / 180.0) * 0.5,
                    sin( 45.0 * CV_PI / 180.0) * sqrt(2.0) * 0.5,
                    sin( 90.0 * CV_PI / 180.0) * 0.5,
                    sin(135.0 * CV_PI / 180.0) * sqrt(2.0) * 0.5,
                    sin(180.0 * CV_PI / 180.0) * 0.5,
                    sin(225.0 * CV_PI / 180.0) * sqrt(2.0) * 0.5,
                    sin(270.0 * CV_PI / 180.0) * 0.5,
                    sin(315.0 * CV_PI / 180.0) * sqrt(2.0) * 0.5};


bool color2Gray(const cv::Mat &inImage, cv::Mat &gray)
{
    switch (inImage.channels())
    {
    case 1:
        gray = inImage;
        return true;
    case 3:
        cv::cvtColor(inImage, gray, cv::COLOR_RGB2GRAY);
        return true;
    case 4:
        cv::cvtColor(inImage, gray, cv::COLOR_RGBA2GRAY);
        return true;
    default:
        break;
    }
    return false;
}

void gradient(const cv::Mat &inImage, cv::Mat gradients16S[8])
{
    cv::Mat grayImage;
    color2Gray(inImage, grayImage);
    cv::filter2D(grayImage, gradients16S[SOBEL_DIR_0  ], CV_16S, sobel[SOBEL_DIR_0  ]);
    cv::filter2D(grayImage, gradients16S[SOBEL_DIR_45 ], CV_16S, sobel[SOBEL_DIR_45 ]);
    cv::filter2D(grayImage, gradients16S[SOBEL_DIR_90 ], CV_16S, sobel[SOBEL_DIR_90 ]);
    cv::filter2D(grayImage, gradients16S[SOBEL_DIR_135], CV_16S, sobel[SOBEL_DIR_135]);
    cv::filter2D(grayImage, gradients16S[SOBEL_DIR_180], CV_16S, sobel[SOBEL_DIR_180]);
    cv::filter2D(grayImage, gradients16S[SOBEL_DIR_225], CV_16S, sobel[SOBEL_DIR_225]);
    cv::filter2D(grayImage, gradients16S[SOBEL_DIR_270], CV_16S, sobel[SOBEL_DIR_270]);
    cv::filter2D(grayImage, gradients16S[SOBEL_DIR_315], CV_16S, sobel[SOBEL_DIR_315]);
}

bool edge(const cv::Mat &inImage, cv::Mat &edge8U, int threshold)
{
    if(inImage.empty()) return false;
    cv::Mat grayImage;
    color2Gray(inImage, grayImage);
    cv::Mat amp, angle;
    amplitudeAndAngle(grayImage, amp, angle);
    ampAngle2Edge(amp, angle, edge8U, threshold);
    return true;
}

bool subPixelEdge(const cv::Mat &inImage, cv::Mat &edge8U, std::vector<cv::Point2f> &points, int threshold)
{
    if(inImage.empty()) return false;
    cv::Mat grayImage;
    color2Gray(inImage, grayImage);
    cv::Mat gradients[8];
    gradient(grayImage, gradients);
    cv::Mat amp, angle;
    gradients2AmpAngle(gradients, amp, angle);
    points = ampAngle2SubPixelEdge(amp, angle, edge8U, threshold);
    return true;
}

bool subPixelEdge(const cv::Mat &inImage, cv::Mat &edge, cv::Mat &coordinate, int threshold)
{
    if(inImage.empty()) return false;
    cv::Mat grayImage;
    color2Gray(inImage, grayImage);
    cv::Mat gradients[8];
    gradient(grayImage, gradients);
    cv::Mat amp, angle;
    gradients2AmpAngle(gradients, amp, angle);
    ampAngle2SubPixelEdge(amp, angle, edge, coordinate, threshold);
    return true;
}

void ampAngle2Edge(const cv::Mat &amp, const cv::Mat &angle, cv::Mat &edge, int threshold)
{
    edge.create(amp.rows, amp.cols, CV_8UC1);
    for (int r = 1; r < amp.rows - 1; r++)
    {
        // 3 * 3 邻域, 所以用3个指针, 一个指针指一行
        const short *pAmp1 = amp.ptr<short>(r - 1);
        const short *pAmp2 = amp.ptr<short>(r);
        const short *pAmp3 = amp.ptr<short>(r + 1);
        const short *pAng = angle.ptr<short>(r);
        uchar *pEdge = edge.ptr<uchar>(r);

        for (int c = 1; c < amp.cols - 1; c++)
        {
            if(pAmp2[c] < threshold) continue;
            switch (pAng[c])
            {
            case SOBEL_DIR_270:////
                if (pAmp2[c] > pAmp1[c] && pAmp2[c] >= pAmp3[c])
                {
                    pEdge[c] = 255;
                }
                break;
            case SOBEL_DIR_90:////
                if (pAmp2[c] >= pAmp1[c] && pAmp2[c] > pAmp3[c])
                {
                    pEdge[c] = 255;
                }
                break;
            case SOBEL_DIR_315:////
                if (pAmp2[c] > pAmp1[c + 1] && pAmp2[c] >= pAmp3[c - 1])
                {
                    pEdge[c] = 255;
                }
                break;
            case SOBEL_DIR_135:////
                if (pAmp2[c] >= pAmp1[c + 1] && pAmp2[c] > pAmp3[c - 1])
                {
                    pEdge[c] = 255;
                }
                break;
            case SOBEL_DIR_0:////
                if (pAmp2[c] >= pAmp2[c - 1] && pAmp2[c] > pAmp2[c + 1])
                {
                    pEdge[c] = 255;
                }
                break;
            case SOBEL_DIR_180:////
                if (pAmp2[c] > pAmp2[c - 1] && pAmp2[c] >= pAmp2[c + 1])
                {
                    pEdge[c] = 255;
                }
                break;
            case SOBEL_DIR_45:////
                if (pAmp2[c] >= pAmp1[c - 1] && pAmp2[c] > pAmp3[c + 1])
                {
                    pEdge[c] = 255;
                }
                break;
            case SOBEL_DIR_225:////
                if (pAmp2[c] > pAmp1[c - 1] && pAmp2[c] >= pAmp3[c + 1])
                {
                    pEdge[c] = 255;
                }
                break;
            default:
                break;
            }
        }
    }
}

std::vector<cv::Point2f> ampAngle2SubPixelEdge(const cv::Mat &amp, const cv::Mat &angle, cv::Mat &edge, int threshold)
{
    edge.create(amp.rows, amp.cols, CV_8UC1);
    std::vector<cv::Point2f> points;
    for (int r = 1; r < amp.rows - 1; r++)
    {
        // 3 * 3 邻域, 所以用3个指针, 一个指针指一行
        const short *pAmp1 = amp.ptr<short>(r - 1);
        const short *pAmp2 = amp.ptr<short>(r);
        const short *pAmp3 = amp.ptr<short>(r + 1);
        const short *pAng = angle.ptr<short>(r);
        uchar *pEdge = edge.ptr<uchar>(r);
        for (int c = 1; c < amp.cols - 1; c++)
        {
            if(pAmp2[c] < threshold) continue;
            double dTmp = 0;
            switch (pAng[c])
            {
            case SOBEL_DIR_270:////
                if (pAmp2[c] > pAmp1[c] && pAmp2[c] >= pAmp3[c])
                {
                    pEdge[c] = 255;
                    dTmp = -((double)pAmp1[c] - pAmp3[c]) / (pAmp1[c] + pAmp3[c] - 2 * pAmp2[c]);
                    break;
                }
                else continue;
            case SOBEL_DIR_90:////
                if (pAmp2[c] >= pAmp1[c] && pAmp2[c] > pAmp3[c])
                {
                    pEdge[c] = 255;
                    dTmp = ((double)pAmp1[c] - pAmp3[c]) / (pAmp1[c] + pAmp3[c] - 2 * pAmp2[c]);
                    break;
                }
                else continue;
            case SOBEL_DIR_315:////
                if (pAmp2[c] > pAmp1[c + 1] && pAmp2[c] >= pAmp3[c - 1])
                {
                    pEdge[c] = 255;
                    dTmp = -((double)pAmp1[c + 1] - pAmp3[c - 1]) / (pAmp1[c + 1] + pAmp3[c - 1] - 2 * pAmp2[c]);
                    break;
                }
                else continue;
            case SOBEL_DIR_135:////
                if (pAmp2[c] >= pAmp1[c + 1] && pAmp2[c] > pAmp3[c - 1])
                {
                    pEdge[c] = 255;
                    dTmp = ((double)pAmp1[c + 1] - pAmp3[c - 1]) / (pAmp1[c + 1] + pAmp3[c - 1] - 2 * pAmp2[c]);
                    break;
                }
                else continue;
            case SOBEL_DIR_0:////
                if (pAmp2[c] >= pAmp2[c - 1] && pAmp2[c] > pAmp2[c + 1])
                {
                    pEdge[c] = 255;
                    dTmp = ((double)pAmp2[c - 1] - pAmp2[c + 1]) / (pAmp2[c - 1] + pAmp2[c + 1] - 2 * pAmp2[c]);
                    break;
                }
                else continue;
            case SOBEL_DIR_180:////
                if (pAmp2[c] > pAmp2[c - 1] && pAmp2[c] >= pAmp2[c + 1])
                {
                    pEdge[c] = 255;
                    dTmp = -((double)pAmp2[c - 1] - pAmp2[c + 1]) / (pAmp2[c - 1] + pAmp2[c + 1] - 2 * pAmp2[c]);
                    break;
                }
                else continue;
            case SOBEL_DIR_45:////
                if (pAmp2[c] >= pAmp1[c - 1] && pAmp2[c] > pAmp3[c + 1])
                {
                    pEdge[c] = 255;
                    dTmp = ((double)pAmp1[c - 1] - pAmp3[c + 1]) / (pAmp1[c - 1] + pAmp3[c + 1] - 2 * pAmp2[c]);
                    break;
                }
                else continue;
            case SOBEL_DIR_225:////
                if (pAmp2[c] > pAmp1[c - 1] && pAmp2[c] >= pAmp3[c + 1])
                {
                    pEdge[c] = 255;
                    dTmp = -((double)pAmp1[c - 1] - pAmp3[c + 1]) / (pAmp1[c - 1] + pAmp3[c + 1] - 2 * pAmp2[c]);
                    break;
                }
                else continue;
            default:
                continue;
            }
            const double x = c + dTmp * xTable[pAng[c]];
            const double y = r + dTmp * yTable[pAng[c]];
            points.push_back(cv::Point2f(x, y));
        }
    }
    return points;
}


void ampAngle2SubPixelEdge(const cv::Mat &amp16S, const cv::Mat &angle16S, cv::Mat &edge8U, cv::Mat &coordinate32F, int threshold)
{
    edge8U.create(amp16S.rows, amp16S.cols, CV_8UC1);
    coordinate32F.create(amp16S.rows, amp16S.cols, CV_32FC2);
    for (int r = 1; r < amp16S.rows - 1; r++)
    {
        // 3 * 3 邻域, 所以用3个指针, 一个指针指一行
        const short *pAmp1 = amp16S.ptr<short>(r - 1);
        const short *pAmp2 = amp16S.ptr<short>(r);
        const short *pAmp3 = amp16S.ptr<short>(r + 1);
        const short *pAng = angle16S.ptr<short>(r);
        uchar *pEdge = edge8U.ptr<uchar>(r);
        float *pCoordinate = coordinate32F.ptr<float>(r);

        for (int c = 1; c < amp16S.cols - 1; c++)
        {
            if(pAmp2[c] < threshold) continue;
            double dTmp = 0;
            switch (pAng[c])
            {
            case SOBEL_DIR_270:////
                if (pAmp2[c] > pAmp1[c] && pAmp2[c] >= pAmp3[c])
                {
                    pEdge[c] = 255;
                    dTmp = -((double)pAmp1[c] - pAmp3[c]) / (pAmp1[c] + pAmp3[c] - 2 * pAmp2[c]);
                    break;
                }
                else continue;
            case SOBEL_DIR_90:////
                if (pAmp2[c] >= pAmp1[c] && pAmp2[c] > pAmp3[c])
                {
                    pEdge[c] = 255;
                    dTmp = ((double)pAmp1[c] - pAmp3[c]) / (pAmp1[c] + pAmp3[c] - 2 * pAmp2[c]);
                    break;
                }
                break;
            case SOBEL_DIR_315:////
                if (pAmp2[c] > pAmp1[c + 1] && pAmp2[c] >= pAmp3[c - 1])
                {
                    pEdge[c] = 255;
                    dTmp = -((double)pAmp1[c + 1] - pAmp3[c - 1]) / (pAmp1[c + 1] + pAmp3[c - 1] - 2 * pAmp2[c]);
                    break;
                }
                else continue;
            case SOBEL_DIR_135:////
                if (pAmp2[c] >= pAmp1[c + 1] && pAmp2[c] > pAmp3[c - 1])
                {
                    pEdge[c] = 255;
                    dTmp = ((double)pAmp1[c + 1] - pAmp3[c - 1]) / (pAmp1[c + 1] + pAmp3[c - 1] - 2 * pAmp2[c]);
                    break;
                }
                else continue;
            case SOBEL_DIR_0:////
                if (pAmp2[c] >= pAmp2[c - 1] && pAmp2[c] > pAmp2[c + 1])
                {
                    pEdge[c] = 255;
                    dTmp = ((double)pAmp2[c - 1] - pAmp2[c + 1]) / (pAmp2[c - 1] + pAmp2[c + 1] - 2 * pAmp2[c]);
                    break;
                }
                else continue;
            case SOBEL_DIR_180:////
                if (pAmp2[c] > pAmp2[c - 1] && pAmp2[c] >= pAmp2[c + 1])
                {
                    pEdge[c] = 255;
                    dTmp = -((double)pAmp2[c - 1] - pAmp2[c + 1]) / (pAmp2[c - 1] + pAmp2[c + 1] - 2 * pAmp2[c]);
                    break;
                }
                else continue;
            case SOBEL_DIR_45:////
                if (pAmp2[c] >= pAmp1[c - 1] && pAmp2[c] > pAmp3[c + 1])
                {
                    pEdge[c] = 255;
                    dTmp = ((double)pAmp1[c - 1] - pAmp3[c + 1]) / (pAmp3[c + 1] + pAmp1[c - 1] - 2 * pAmp2[c]);
                    break;
                }
                else continue;
            case SOBEL_DIR_225:////
                if (pAmp2[c] > pAmp1[c - 1] && pAmp2[c] >= pAmp3[c + 1])
                {
                    pEdge[c] = 255;
                    dTmp = -((double)pAmp1[c - 1] - pAmp3[c + 1]) / (pAmp3[c + 1] + pAmp1[c - 1] - 2 * pAmp2[c]);
                    break;
                }
                else continue;
            default:
                continue;
            }
            const double x = c + dTmp * xTable[pAng[c]];
            const double y = r + dTmp * yTable[pAng[c]];
            pCoordinate[2 * c] = (float)x;
            pCoordinate[2 * c + 1] = (float)y;
        }
    }
}

void gradients2AmpAngle(cv::Mat gradients[8], cv::Mat &ampAndAngle)
{
    ampAndAngle.create(gradients[0].rows, gradients[0].cols, CV_16SC2);
    const short angle_list[] = { SOBEL_DIR_0, SOBEL_DIR_45, SOBEL_DIR_90, SOBEL_DIR_135, SOBEL_DIR_180, SOBEL_DIR_225, SOBEL_DIR_270, SOBEL_DIR_315 };
    for (int r = 0; r < ampAndAngle.rows; r++)
    {
        short *pAmp = ampAndAngle.ptr<short>(r);
        short *pAng = ampAndAngle.ptr<short>(r) + 1;

        short *pGrad[8] = {nullptr};
        for (int i = 0; i < 8; i++)
        {
            pGrad[i] = gradients[i].ptr<short>(r);
        }

        for (int c = 0; c < ampAndAngle.cols; c++)
        {
            // 找出最大值
            for (int i = 0; i < 8; i++)
            {
                if (pAmp[2 * c] < pGrad[i][c])
                {
                    pAmp[2 * c] = pGrad[i][c];
                    pAng[2 * c] = angle_list[i];
                }
            }
        }
    }
}

void gradients2AmpAngle(cv::Mat gradients[8], cv::Mat &amp, cv::Mat &angle16S)
{
    amp.create(gradients[0].rows, gradients[0].cols, CV_16SC1);
    angle16S.create(gradients[0].rows, gradients[0].cols, CV_16SC1);
    const short angle_list[] = { SOBEL_DIR_0, SOBEL_DIR_45, SOBEL_DIR_90, SOBEL_DIR_135, SOBEL_DIR_180, SOBEL_DIR_225, SOBEL_DIR_270, SOBEL_DIR_315 };
    for (int r = 0; r < amp.rows; r++)
    {
        short *pAmp = amp.ptr<short>(r);
        short *pAng = angle16S.ptr<short>(r);

        short *pGrad[8] = {nullptr};
        for (int i = 0; i < 8; i++)
        {
            pGrad[i] = gradients[i].ptr<short>(r);
        }

        for (int c = 0; c < amp.cols; c++)
        {
            // 找出最大值
            for (int i = 0; i < 8; i++)
            {
                if (pAmp[c] < pGrad[i][c])
                {
                    pAmp[c] = pGrad[i][c];
                    pAng[c] = angle_list[i];
                }
            }
        }
    }
}

bool amplitudeAndAngle(const cv::Mat &inImage, cv::Mat &amp, cv::Mat &angle)
{
    if(inImage.empty()) return false;
    cv::Mat grayImage;
    color2Gray(inImage, grayImage);
    cv::Mat gradients[8];
    gradient(grayImage, gradients);
    gradients2AmpAngle(gradients, amp, angle);
    return true;
}

bool gradient(const cv::Mat &inImage, cv::Mat &gradImage, SOBEL_DIR dir)
{
    if(inImage.empty()) return false;
    cv::Mat grayImage;
    color2Gray(inImage, grayImage);
    cv::filter2D(grayImage, gradImage, CV_16S, sobel[dir]);
//    cv::normalize(gradImage, gradImage, 0, 255, cv::NORM_MINMAX);
    return true;
}

bool dirEdge(const cv::Mat inImage, cv::Mat &edge, SOBEL_DIR dir, int threshold)
{
    if(inImage.empty()) return false;
    cv::Mat gradientImage(inImage.rows, inImage.cols, CV_16SC1, cv::Scalar(0)), grayImage;
    color2Gray(inImage, grayImage);
    cv::filter2D(grayImage, gradientImage, CV_16S, sobel[dir]);
//    edge.create(inImage.rows, inImage.cols, CV_8UC1);
    switch (dir)
    {
    case SOBEL_DIR_0:////
        for (int r = 1; r < gradientImage.rows - 1; r++)
        {
            short *pAmp2 = gradientImage.ptr<short>(r);
            for (int c = 1; c < gradientImage.cols - 1; c++)
            {
                if (pAmp2[c] >= pAmp2[c - 1] && pAmp2[c] > pAmp2[c + 1] && pAmp2[c] >= threshold)
                {
                    pAmp2[c] = 255;
                }
                else
                {
                    pAmp2[c] = 0;
                }
            }
        }
        break;
    case SOBEL_DIR_180:////
        for (int r = 1; r < gradientImage.rows - 1; r++)
        {
            short *pAmp2 = gradientImage.ptr<short>(r);
            for (int c = 1; c < gradientImage.cols - 1; c++)
            {
                if (pAmp2[c] > pAmp2[c - 1] && pAmp2[c] >= pAmp2[c + 1] && pAmp2[c] >= threshold)
                {
                    pAmp2[c] = 255;
                }
                else
                {
                    pAmp2[c] = 0;
                }
            }
        }
        break;
    case SOBEL_DIR_90:////
        for (int r = 1; r < gradientImage.rows - 1; r++)
        {
            short *pAmp1 = gradientImage.ptr<short>(r - 1);
            short *pAmp2 = gradientImage.ptr<short>(r);
            short *pAmp3 = gradientImage.ptr<short>(r + 1);
            for (int c = 1; c < gradientImage.cols - 1; c++)
            {
                if (pAmp2[c] >= pAmp1[c] && pAmp2[c] > pAmp3[c] && pAmp2[c] >= threshold)
                {
                    pAmp2[c] = 255;
                }
                else
                {
                    pAmp2[c] = 0;
                }
            }
        }
        break;
    case SOBEL_DIR_270:////
        for (int r = 1; r < gradientImage.rows - 1; r++)
        {
            short *pAmp1 = gradientImage.ptr<short>(r - 1);
            short *pAmp2 = gradientImage.ptr<short>(r);
            short *pAmp3 = gradientImage.ptr<short>(r + 1);
            for (int c = 1; c < gradientImage.cols - 1; c++)
            {
                if (pAmp2[c] > pAmp1[c] && pAmp2[c] >= pAmp3[c] && pAmp2[c] >= threshold)
                {
                    pAmp2[c] = 255;
                }
                else
                {
                    pAmp2[c] = 0;
                }
            }
        }
        break;
    case SOBEL_DIR_315:////
        for (int r = 1; r < gradientImage.rows - 1; r++)
        {
            short *pAmp1 = gradientImage.ptr<short>(r - 1);
            short *pAmp2 = gradientImage.ptr<short>(r);
            short *pAmp3 = gradientImage.ptr<short>(r + 1);
            for (int c = 1; c < gradientImage.cols - 1; c++)
            {
                if (pAmp2[c] > pAmp1[c + 1] && pAmp2[c] >= pAmp3[c - 1] && pAmp2[c] >= threshold)
                {
                    pAmp2[c] = 255;
                }
                else
                {
                    pAmp2[c] = 0;
                }
            }
        }
        break;
    case SOBEL_DIR_135:////
        for (int r = 1; r < gradientImage.rows - 1; r++)
        {
            short *pAmp1 = gradientImage.ptr<short>(r - 1);
            short *pAmp2 = gradientImage.ptr<short>(r);
            short *pAmp3 = gradientImage.ptr<short>(r + 1);
            for (int c = 1; c < gradientImage.cols - 1; c++)
            {
                if (pAmp2[c] >= pAmp1[c + 1] && pAmp2[c] > pAmp3[c - 1] && pAmp2[c] >= threshold)
                {
                    pAmp2[c] = 255;
                }
                else
                {
                    pAmp2[c] = 0;
                }
            }
        }
        break;
    case SOBEL_DIR_45:////
        for (int r = 1; r < gradientImage.rows - 1; r++)
        {
            short *pAmp1 = gradientImage.ptr<short>(r - 1);
            short *pAmp2 = gradientImage.ptr<short>(r);
            short *pAmp3 = gradientImage.ptr<short>(r + 1);
            for (int c = 1; c < gradientImage.cols - 1; c++)
            {
                if (pAmp2[c] >= pAmp1[c - 1] && pAmp2[c] > pAmp3[c + 1] && pAmp2[c] >= threshold)
                {
                    pAmp2[c] = 255;
                }
                else
                {
                    pAmp2[c] = 0;
                }
            }
        }
        break;
    case SOBEL_DIR_225:////
        for (int r = 1; r < gradientImage.rows - 1; r++)
        {
            short *pAmp1 = gradientImage.ptr<short>(r - 1);
            short *pAmp2 = gradientImage.ptr<short>(r);
            short *pAmp3 = gradientImage.ptr<short>(r + 1);
            for (int c = 1; c < gradientImage.cols - 1; c++)
            {
                if (pAmp2[c] > pAmp1[c - 1] && pAmp2[c] >= pAmp3[c + 1] && pAmp2[c] >= threshold)
                {
                    pAmp2[c] = 255;
                }
                else
                {
                    pAmp2[c] = 0;
                }
            }
        }
        break;
    }
    gradientImage.convertTo(edge, CV_8UC1, 1, 0); // 将 CV_16SC1 图像转换为 CV_8UC1 图像
    return true;
}

}
